package com.yupi.yuojcodesandbox.docker;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.api.model.PullResponseItem;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.command.LogContainerResultCallback;

import java.util.List;

public class DockerDemo {
    public static void main(String[] args) throws InterruptedException {
        DockerClient dockerClient = DockerClientBuilder.getInstance().build();
        //拉取镜像
        String image = "nginx:latest";
        //使用docker拉取镜像
//        PullImageCmd pullImageCmd = dockerClient.pullImageCmd(image);
//        //回调函数
//        PullImageResultCallback pullImageResultCallback = new PullImageResultCallback() {
//            @Override
//            public void onNext(PullResponseItem item) {
//                //没下载一个阶段都会打印一次
//                System.out.println("下载镜像：" + item.getStatus());
//                //onNext表示镜像每下载一个阶段就会触发一次onNext方法 用异步就是因为下载的时间可能非常长不可能等全部下载完 所以是一段一段执行的
//                super.onNext(item);
//            }
//        };
//        pullImageCmd
//                //exec是执行操作 参数是一个回调用于得知镜像拉取之后需要做的事情 且是异步的
//                .exec(pullImageResultCallback)
//                //awaitCompletion的作用就是阻塞 等到镜像下载完成才会执行下一步 程序如果没有下载完就会一直卡在这里
//                .awaitCompletion();
//        System.out.println("下载完成");


        //创建容器
        CreateContainerCmd containerCmd = dockerClient.createContainerCmd(image);
        CreateContainerResponse createContainerResponse = containerCmd
                //withCmd表示执行容器启动容器的时候自动执行的命令
                .withCmd("echo","hello docker")
                .exec();
        System.out.println(createContainerResponse);
        String containerId = createContainerResponse.getId();

        //查看容器状态
        ListContainersCmd listContainersCmd = dockerClient.listContainersCmd();
        List<Container> containerList = listContainersCmd.withShowAll(true).exec();
        for (Container container : containerList) {
            System.out.println(container);
        }

        //启动容器
        StartContainerCmd startContainerCmd = dockerClient.startContainerCmd(containerId);
        startContainerCmd.exec();

        //可能存在一种请情况就是启动容器的操纵是异步 也就是当容器都没有启动完成的时候就查看了日志 所以日志就会没有信息 所以调式的时候可以让启动容器的操作进行随眠
        //或者有一个阻塞的程序等到启动容器的方法结束后在进行后面的操作
//        Thread.sleep(10000L);

        //查看某个容器的日志 读取日志的参数是回调的也是异步的 每读取一批输出一批 而不是全部读完在一起输出
        //因为日志信息可能很大 不可能让程序一直在读取从而卡死
        // 查看日志
        LogContainerResultCallback logContainerResultCallback = new LogContainerResultCallback() {
            @Override
            public void onNext(Frame item) {
                System.out.println(item.getStreamType());
                System.out.println("日志：" + new String(item.getPayload()));
                super.onNext(item);
            }
        };

        //阻塞等待日志输出
        dockerClient.logContainerCmd(containerId)
                //开启容器的错误输出和标准输出
                .withStdErr(true)
                .withStdOut(true)
                .exec(logContainerResultCallback)
                //日志操作可能执行的比较快在容器启动之前就执行了 所以捕获不到日志 所以需要阻塞日志的操作
                .awaitCompletion();

        //删除容器 底层大概是把命令行的参数变成了with的语言进行了命令的拼装
        dockerClient.removeContainerCmd(containerId).withForce(true).exec();

        //删除镜像
//        dockerClient.removeImageCmd(image).exec();

    }
}
